<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <title>True clock</title>
<style>
    html, body {
        margin: 0px;
        padding: 0px;
    }
    .earth-container-ext {
        margin: 5em;
    }
    .earth-container-int {
        padding: 2em;
        background-color: #000000;
    }
    .earth {
        position: relative;
        width: 300px;
        height: 150px;

        background-image: url(earth.png);
        background-position: 0px 0px;
    }
    .earth-shadow {
        position: absolute;
        top: 0px;
        left: 0px;
        width: 300px;
        height: 150px;

        opacity: 1;
        background-position: 0px 0px;
    }
</style>
<script>

function buildDOM(data, doc, context)
{
    if (! doc) {
        doc = document;
    }
    if (typeof context != 'object') {
        context = null;
    }

    if (((typeof data) != 'object') && ((typeof data) != 'string')) {
        data = new String(data);
    }

    var dataType = null;
    if (typeof data == 'object') {
        var isDOM = false;
        try {
            isDOM = (((typeof data.cloneNode) == 'function') || ((typeof data.cloneNode) == 'object'));
        } catch (e) {}

        if (isDOM) {
            dataType = 'DOM';
        } else {
            dataType = ((data instanceof Array)
                ? 'Array'
                : ((data instanceof String)
                    ? 'String'
                    : 'Object'
                )
            );
        }
    } else if (typeof data == 'string') {
        dataType = 'String';
    }

    if (! context) {
        var result = null;
        switch (dataType) {

        case 'DOM':
            return data;

        case 'Object':
            for (var field in data) {
                if (field.indexOf('@') != 0) {
                    result = doc.createElement(field);
                    buildDOM(data[field], doc, result);
                    return result;
                }
                break;
            }
            break;

        case 'Array':
            if (data.length > 0) {
                return buildDOM(data[0], doc);
            }
            break;

        case 'String':
            return doc.createTextNode(data);
        }
    } else {
        var tmp = null;
        switch (dataType) {

        case 'DOM':
            context.appendChild(data);
            break;

        case 'Object':
            for (var field in data) {
                if (field.indexOf('@') != 0) {
                    tmp = doc.createElement(field);
                    buildDOM(data[field], doc, tmp);
                    context.appendChild(tmp);
                } else {
                    context.setAttribute(field.substr(1), data[field]);
                }
            }
            break;

        case 'Array':
            for (var i = 0; i < data.length; i++) {
                buildDOM(data[i], doc, context);
            }
            break;

        case 'String':
            context.appendChild(doc.createTextNode(data));
        }

        return context;
    }

    return null;
}


function GUITimer()
{
    this.getMicrotime = function()
    {
        var d = new Date();
        return ((d.getHours() * 3600) + (d.getMinutes() * 60) + d.getSeconds() + (d.getMilliseconds() / 1000));
    }

    this.startTime = this.getMicrotime();

    this.getTime = function()
    {
        return (this.getMicrotime() - this.startTime);
    }

    this.reset = function()
    {
        var res = this.getTime();
        this.startTime = this.getMicrotime();
        return res;
    }
}

var GUILimitedEventTimer_obj = null;
var GUILimitedEventTimer_F1 = null;
var GUILimitedEventTimer_F2 = null;

function GUILimitedEventTimer(callback, interval, limit)
{
    this.stoper = function()
    {
        clearInterval(this.intervalID);
    }
    this.callback = callback;
    GUILimitedEventTimer_obj = this;
    GUILimitedEventTimer_F1 = function(){GUILimitedEventTimer_obj.callback();};
    GUILimitedEventTimer_F2 = function(){GUILimitedEventTimer_obj.stoper();};

    this.intervalID = setInterval('GUILimitedEventTimer_F1();', interval);
    if (limit != null) {
        this.timeoutID  = setTimeout('GUILimitedEventTimer_F2();', limit);
    }

    this.stop = function()
    {
        clearTimeout(this.timeoutID);
        this.stoper();
    }
}
</script>
</head>
<body>
    <table class="earth-container-ext" border="0" cellpadding="0" cellspacing="0"><tr><td>
    <div class="earth-container-int">
        <div id="earth" class="earth">
        </div>
    </div>
    </td></tr></table>
    <p>Sun: <span id="sunAngle"></span></p>
<script type="text/javascript">

var e = document.getElementById('earth');
var sunShodow = [];

for (var i = 1; i <= 65; i++) {
    sunShodow[i-1] = e.appendChild(buildDOM({'div':{'@id': 'sunShodow' + (i < 10 ? '0' : '') + i,
                                               '@class': 'earth-shadow',
                                               '@style': 'background-image: url(earth-shadows/' + (i < 10 ? '0' : '') + i + '.png)'}
                                         }));
}

var sunAngleBox = document.getElementById('sunAngle');

function sunPointCoords()
{
    /*
    Суток между равноденствиями 365,2424
    Наклон эклиптики 23 градуса
    Точка отчёта 0 меридиан (long: 180), 0 широты (lat: 90) 21.01.2003 01:00

    long: [0; 360] С востока на запад.
    lat: [0; 180] С севера на юг.

    */
    return {'lat': 0, 'long': 0}
}

function getOpaticyForAreaNum(areaNum, sunLong, sunLat)
{
    /*
    areaNum: [0;lattitudes*longtitudes)

    Долгота (longtitude) измеряеться с востока на запад относительно Гринвичского меридиана.

    */

    // Кол-во сегментов-параллелей.
    var lattitudes = 5;

    // Кол-во сегментов-меридиан.
    var longtitudes = 13;

    var longtitudeLength = 360/longtitudes;

    // Меняем направление нумерации сегментов по возрастанию с востока на запад.
    var latNum = longtitudes - 1 - Math.floor(areaNum / lattitudes);


    // Долгота восточного края первого сегмента-меридиана (latNum = 0).
    var long0 = 170;

    var angleOfMiddleLongtitude = (((latNum+0.5))*longtitudeLength + long0);
    while (angleOfMiddleLongtitude < 0) {
        angleOfMiddleLongtitude += 360;
    }
    while (angleOfMiddleLongtitude >= 360) {
        angleOfMiddleLongtitude -= 360;
    }
    if (areaNum % lattitudes == 0) {
        //alert(Math.floor(angleOfMiddleLongtitude));
    }
    var angle = angleOfMiddleLongtitude - sunLong;

    var f = Math.abs(Math.abs(angleOfMiddleLongtitude - sunLong) - 180) < 90;

    var opacity = !f ? 1 - Math.abs(Math.cos(Math.PI*angle/180)) : 1;


    return opacity;
}

function refreshLight(date)
{
    var secondsOfGreenwichDayStart = (date.getHours()*3600 + date.getMinutes()*60 + date.getSeconds());
    var sunLong = (secondsOfGreenwichDayStart/86400)*360;

    //sunAngleBox.innerHTML = Math.floor(sunLong);

    for (var i = 0; i < 65; i++) {
        sunShodow[i].style.opacity = getOpaticyForAreaNum(i, sunLong, 0);//!!!
    }
}
var g = null;
g = new Date();
var currHours = g.getHours();

g.setHours(currHours > 22 ? currHours - 22 : currHours + 2);
refreshLight(g);

//alert(g.getHours());

/*
var increment = 1;

var timer = new GUILimitedEventTimer(function call()
{
    increment++;

    var d = new Date();
    d.setHours(increment % (24*3));
    d.setMinutes((increment % 3)*20);
    d.setSeconds(0);
    d.setMilliseconds(0);
    refreshLight(d);
}, 300);
*/
</script>
</body>
</html>